
import java.io.*;
import java.util.*;
//import java.text.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.xpath.*;

public class mainProcessing {

	public static void main(String[] args) {
		
		try{
			//Open file for processing
			SystemXmlFile xfile = new SystemXmlFile("systemdata.xml");
			//SystemXmlFile xfile = new SystemXmlFile("src/systemdata.xml");
			//Create CLI interface (named GUI for some dumb reason)
			ProcessingUI gui = new ProcessingUI(xfile);
			//Start the UI
			gui.loginUI();
			//Let's rock!
			//CTRL + C to exit at this point in time
		}
		catch(Exception exp) {
			System.err.println(exp.toString());
		}
		
		return;
	}


	
	
	


	static public class SystemXmlFile
	{
		public Document xmlFile;
		public XPath xpath;
		public String filename;
		
		public SystemXmlFile(String newfilename)
		{
			//Constructor
			try {
				filename = newfilename;
				DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
				domFactory.setNamespaceAware(true);
		        DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
		        xmlFile = domBuilder.parse(filename);
		        
		        XPathFactory factory = XPathFactory.newInstance();
		        xpath = factory.newXPath();
		        
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
		}
		
		public void updateXMLFile()
		{
			//This will update the XML File to the current DOM
			System.out.println("Updating XML");
			try {
				// Prepare the DOM document for writing
	            Source source = new DOMSource(xmlFile);
	    
	            // Prepare the output file
	            File file = new File(filename);
	            Result result = new StreamResult(file);
	    
	            // Write the DOM document to the file
	            Transformer xformer = TransformerFactory.newInstance().newTransformer();
	            xformer.transform(source, result);
			}
			catch (Exception exp) {
				System.err.println(exp.toString());
			}
			return;
		}
		
		public String toCSV(NodeList nodes)
		{
			//This function will take in a NodeList,
			//and turn it into a list of comma seperated values
			//then return that list.
			String output = "";
			String nodedata = "";
			
		    for (int i = 0; i < nodes.getLength(); i++) {
		    	nodedata = nodes.item(i).getNodeValue();
		    	if (i != 0) {
		    		output += ",";
		    	}
		    	output += nodedata;
		    }
			
			return output;
		}
		
		public int testLogin(String username, String password)
		{
			//This function will see if any /data/students/student nodes exist with an ID
			//and password that match the variables parsed
			//Will return 0 if invalid login, 1 if student and 2 if staff
			try {
			    XPathExpression expr = xpath.compile("//users/user/id/text()");
			    NodeList nodes = (NodeList) expr.evaluate(xmlFile, XPathConstants.NODESET);
			    
				for (int i = 0; i < nodes.getLength(); i++) {
					String potentialuserid = nodes.item(i).getNodeValue();
					
					XPathExpression expr2 = xpath.compile("//users/user[id='" + potentialuserid + "']/password/text()");
					Node passwordnode = (Node) expr2.evaluate(xmlFile, XPathConstants.NODE);
					String potentialpassword = passwordnode.getNodeValue();
					
					if (potentialuserid.equals(username) && potentialpassword.equals(password))
					{
						//valid login
						//Check to see if staff member or student
					    XPathExpression stustaffexpr = xpath.compile("//users/user[id='"+potentialuserid+"' and @type='staff']");
					    NodeList staffnodes = (NodeList) stustaffexpr.evaluate(xmlFile, XPathConstants.NODESET);
					    if (staffnodes.getLength() == 1 )
					    {
					    	//Staff Member
					    	return 2;
					    }
					    else
					    {
					    	//Student
					    	return 1;
					    }
					    
					}
			    }
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
			//invalid login
			return 0;
		}
		
		
		public String[] getStudentInfo(String studentid)
		{
			//This function will return a string array containing details of
			//a particular student id = 0, firstname = 1, lastname = 2, password = 3
			//and comma-seperated subject ids as 4 and comma-seperated subjectnames as 5
			try {
			    XPathExpression fnameexpr = xpath.compile("//users/user[id='" + studentid + "']/firstname/text()");
			    XPathExpression lnameexpr = xpath.compile("//users/user[id='" + studentid + "']/lastname/text()");
			    XPathExpression passexpr = xpath.compile("//users/user[id='" + studentid + "']/password/text()");
			    XPathExpression unitexpr = xpath.compile("//users/user[id='" + studentid + "']/subjects/subject/text()");
			    Node fnamenode = (Node) fnameexpr.evaluate(xmlFile, XPathConstants.NODE);
			    Node lnamenode = (Node) lnameexpr.evaluate(xmlFile, XPathConstants.NODE);
			    Node passnode = (Node) passexpr.evaluate(xmlFile, XPathConstants.NODE);
			    NodeList units = (NodeList) unitexpr.evaluate(xmlFile, XPathConstants.NODESET);
			    
			    String unitlist = toCSV(units);

			    
			    String unitname = "";
			    String unitnamelist = "";
			    String[] unitidarray = unitlist.split(",");
			    for (int i = 0; i < unitidarray.length; i++) {
			    	//Look up the name for each unit ID
			    	XPathExpression unitnameexpr = xpath.compile("//subjects/subject[id='"+unitidarray[i]+"']/name/text()");
			    	Node unitnamenode = (Node) unitnameexpr.evaluate(xmlFile, XPathConstants.NODE);
			    	unitname = unitnamenode.getNodeValue();
			    	if (i != 0) {
			    		unitnamelist += ",";
			    	}
			    	unitnamelist += unitname;
			    }
			    
			    String[] outputstring = new String[6];
			    outputstring[0] = studentid;
			    outputstring[1] = fnamenode.getNodeValue();
			    outputstring[2] = lnamenode.getNodeValue();
			    outputstring[3] = passnode.getNodeValue();
			    outputstring[4] = unitlist;
			    outputstring[5] = unitnamelist;
			    
			    return outputstring;
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
			return new String[0];
		}
		
		public String[] getAssignmentInfo(String studentid, String subjectid)
		{
			//This function will get return both the assignment names as 1
			//due dates as 2 and total marks as 3 and if submitted by student as 4
			try {
				XPathExpression assignlistexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment/title/text()");
				NodeList assignmentnames = (NodeList) assignlistexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				XPathExpression duedatelistexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment/due/text()");
				NodeList duedates = (NodeList) duedatelistexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				String assignmentnamelist = toCSV(assignmentnames);
				
				String duedatelist = toCSV(duedates);
				
				String submissionmadelist = "";
				String submissionmade = "";
				String totalworth = "";
				String totalworthlist = "";
				String totalawarded = "";
				String totalawardedlist = "";
				for (int i = 0; i < assignmentnames.getLength(); i++) {
					//Get If Submitted for this subject
					String assignmentname = assignmentnames.item(i).getNodeValue();
					XPathExpression submissionmadeexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']/recieved/text()");
					NodeList submissionsmade = (NodeList) submissionmadeexpr.evaluate(xmlFile, XPathConstants.NODESET);
					
					if(submissionsmade.getLength() != 0)
					{
						submissionmade = submissionsmade.item(0).getNodeValue();
					}
					else
					{
						submissionmade = "Not Submitted";
					}
					
			    	if (i != 0) {
			    		submissionmadelist += ",";
			    	}
			    	submissionmadelist += submissionmade;
			    	

			    	
			    	//Get Worth Marks for this subject
			    	XPathExpression allworthexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/markingscheme/criteria/worth/text()");
					NodeList allworth = (NodeList) allworthexpr.evaluate(xmlFile, XPathConstants.NODESET);
					
					//calculate total worth for this assignment
					int totalmarksint = 0;
					for (int j = 0; j < allworth.getLength(); j++) {
						String thismark = allworth.item(j).getNodeValue();
						totalmarksint += Integer.valueOf(thismark);
					}
					totalworth = String.valueOf(totalmarksint);
					
					if (i != 0) {
			    		totalworthlist += ",";
			    	}
			    	totalworthlist += totalworth;
			    	
			    	//Get Awarded Marks for this student and subject
			    	XPathExpression allawardedmarksexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']/marks/mark/score/text()");
					NodeList allawarded = (NodeList) allawardedmarksexpr.evaluate(xmlFile, XPathConstants.NODESET);
					
					//calculate total worth for this assignment
					int totalmarksawardedint = 0;
					for (int j = 0; j < allawarded.getLength(); j++) {
						String thisawardedmark = allawarded.item(j).getNodeValue();
						totalmarksawardedint += Integer.valueOf(thisawardedmark);
					}
					totalawarded = String.valueOf(totalmarksawardedint);
					
					if (i != 0) {
			    		totalawardedlist += ",";
			    	}
					totalawardedlist += totalawarded;
			    	
				}
				
		    	String[] output = new String[5];
		    	output[0] = assignmentnamelist;
		    	output[1] = duedatelist;
		    	output[2] = totalawardedlist;
		    	output[3] = submissionmadelist;
		    	output[4] = totalworthlist;
		    	return output;
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
			
			return new String[0];
		}
		
		
		public String[] getCriteriaInfo(String studentid, String subjectid, String assignmentname)
		{
			try {
				//For each criteria get:
				//1 - Criteria Name
				//2 - Criteria Description
				//3 - Maximum Marks
				//4 - Student's Marks
				//5 - Student's Feedback
				//6 - Marked By
				
				String criterianamelist = "";
				String criteriadesclist = "";
				String maximummarklist = "";
				String studentmarklist = "";
				String studentfeedbacklist = "";
				String markedbylist = "";
				
				//Assignment Specific XPATHS
		    	XPathExpression criterianameexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/markingscheme/criteria/name/text()");
				NodeList criterianamenodes = (NodeList) criterianameexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				XPathExpression criteriadescexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/markingscheme/criteria/description/text()");
				NodeList criteriadescnodes = (NodeList) criteriadescexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				XPathExpression maxmarkexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/markingscheme/criteria/worth/text()");
				NodeList maxmarknodes = (NodeList) maxmarkexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				//Assignment + Student Specific XPATHS
				XPathExpression studentmarkexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']/marks/mark/score/text()");
				NodeList studentmarknodes = (NodeList) studentmarkexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				XPathExpression studentfeedbackexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']/marks/mark/feedback/text()");
				NodeList studentfeedbacknodes = (NodeList) studentfeedbackexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				XPathExpression markedbyexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']/marks/mark/by/text()");
				NodeList markedbynodes = (NodeList) markedbyexpr.evaluate(xmlFile, XPathConstants.NODESET);
				
				String criterianame = "";
				for (int i = 0; i < criterianamenodes.getLength(); i++) {
					criterianame = criterianamenodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		criterianamelist += ",";
			    	}
			    	criterianamelist += criterianame;
			    }
				
				String criteriadesc = "";
				for (int i = 0; i < criteriadescnodes.getLength(); i++) {
					criteriadesc = criteriadescnodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		criteriadesclist += ",";
			    	}
			    	criteriadesclist += criteriadesc;
			    }
				
				String maxmark = "";
				for (int i = 0; i < maxmarknodes.getLength(); i++) {
					maxmark = maxmarknodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		maximummarklist += ",";
			    	}
			    	maximummarklist += maxmark;
			    }

				String studentmark = "";
				for (int i = 0; i < studentmarknodes.getLength(); i++) {
					studentmark = studentmarknodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		studentmarklist += ",";
			    	}
			    	studentmarklist += studentmark;
			    }
				
				String studentfeedback = "";
				for (int i = 0; i < studentfeedbacknodes.getLength(); i++) {
					studentfeedback = studentfeedbacknodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		studentfeedbacklist += ",";
			    	}
			    	studentfeedbacklist += studentfeedback;
			    }
				
				String markedby = "";
				for (int i = 0; i < markedbynodes.getLength(); i++) {
					markedby = markedbynodes.item(i).getNodeValue();
			    	if (i != 0) {
			    		markedbylist += ",";
			    	}
			    	markedbylist += markedby;
			    }
				
				String[] output = new String[6];
				output[0] = criterianamelist;
				output[1] = criteriadesclist;
				output[2] = maximummarklist;
				output[3] = studentmarklist;
				output[4] = studentfeedbacklist;
				output[5] = markedbylist;
				return output;
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
			return new String[0];
		}
		
		
		
		
		
		public boolean makeSubmission(String studentid, String subjectid, String assignmentname)
		{
			//NOTE: This function is not yet implemented.
			
			try {
				//Get the node containing all submissions for this assignment
				XPathExpression submitsnodeexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions");
				Element submissionsnode = (Element) submitsnodeexpr.evaluate(xmlFile, XPathConstants.NODE);
				
				//Get all the submission nodes for this assignment made by
				//the current student, this is used to determine if a student
				//has submitted or not.
				XPathExpression submissioncountexpr = xpath.compile("//subjects/subject[id='"+subjectid+"']/assignments/assignment[title='"+assignmentname+"']/submissions/submission[studentid='"+studentid+"']");
				NodeList units = (NodeList) submissioncountexpr.evaluate(xmlFile, XPathConstants.NODESET);
				if ( units.getLength() == 1 )
				{
					//Submission has already been made, delete and create new submission
					
					System.out.println("Submission Already Exists!");
					System.out.println("Deleting Current Submission!");
					Element submissionelement = (Element) units.item(0);
					//Delete
					submissionsnode.removeChild(submissionelement);
					//Update File
					updateXMLFile();
				}
				//Submission has yet to be made, create submission
					
				Element submissionnode = xmlFile.createElement("submission");
				submissionnode.appendChild(xmlFile.createTextNode(""));
				
				Element studentidnode = xmlFile.createElement("studentid");
				studentidnode.appendChild(xmlFile.createTextNode(studentid));
				
				Date date=new Date();
				String datestring = date.toString();
				Element recievednode = xmlFile.createElement("recieved");
				recievednode.appendChild(xmlFile.createTextNode(datestring));
				
				//Join studentid and recieved nodes to submission node.
				submissionnode.appendChild(studentidnode);
				submissionnode.appendChild(recievednode);
				
				//Finally, join the submission node to the submissionS node
				submissionsnode.appendChild(submissionnode);
				
				//Update the XML File to reflect the changed DOM
				updateXMLFile();
				System.out.println("");
				System.out.println("Submission made OK");
				System.out.println("");
					
				
				System.out.println(units.getLength());
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}

			
			
			return true;
		}
	}



	static public class ProcessingUI
	{
		public BufferedReader in;
		public SystemXmlFile xmldata;
		
		public ProcessingUI(SystemXmlFile infile)
		{
			//Constructor
			//Setup Input StreamReader
			InputStreamReader converter = new InputStreamReader(System.in);
			in = new BufferedReader(converter);
			xmldata = infile;
		}
		
		public void loginUI()
		{
			try {
				System.out.println("Welcome to the Darwin");
				System.out.println("Online Submission System");
				System.out.println("");
				
				String username = "";
				String password = "";
				
				int usernameok = 0;
				while (usernameok == 0){
					System.out.println("Please enter your Username:");
					username = in.readLine();
					System.out.println("Please enter your Password:");
					password = in.readLine();
					usernameok = xmldata.testLogin(username, password);
					if (usernameok == 1)
					{
						System.out.println("");
						System.out.println("Student Login Succesfull!");
						System.out.println("");
						//go to next view with studentid
						studentUnitListUI(username);
					}
					else if (usernameok == 2)
					{
						System.out.println("");
						System.out.println("Staff Login Succesfull!");
						System.out.println("");
					}
					else
					{
						System.out.println("");
						System.out.println("Incorrect Username or Password");
						System.out.println("");
					}
				}
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
		}
		
		
		public void studentUnitListUI(String userid)
		{
			try {
				String[] studentinfo = xmldata.getStudentInfo(userid);
				
				int unitcount = studentinfo[4].split(",").length;
				
				//Welcome Steve Smith
				System.out.println("");
				System.out.println("Welcome " + studentinfo[1] + " " + studentinfo[2]);
				System.out.println("");
				
				for (int i = 0; i < unitcount; i++) {
					// 1 - HIT1412 - Java Technologies
					String unitno = Integer.toString(i+1);
					String unitid = studentinfo[4].split(",")[i];
					String unitname = studentinfo[5].split(",")[i];
					System.out.println(unitno + " - " + unitid + " " + unitname);
				}
				System.out.println("");
				System.out.println("Enter the number of the unit you wish to");
				System.out.println("view and press enter. Use 0 to go back.");
				
				int inputchoice = Integer.parseInt(in.readLine());
				if (inputchoice == 0)
				{
					//Go Back
					loginUI();
				}
				else if(inputchoice > 0 && inputchoice <= unitcount)
				{
					//Go to view for unit
					studentAssignmentListUI(userid, studentinfo[4].split(",")[inputchoice - 1]);
				}
				else
				{
					//Something screwed up, recall this view.
					System.out.println("Invalid number entered, please try again");
					studentUnitListUI(userid);
				}
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
		}
		
		public void studentAssignmentListUI(String studentid, String unitid)
		{
			try {
				String[] assignmentdata = xmldata.getAssignmentInfo(studentid, unitid);
				int assignmentcount = assignmentdata[0].split(",").length;
				
				System.out.println("Assignments for " + unitid);
				System.out.println("");
				
				for (int i = 0; i < assignmentcount; i++) {
					//[0] Assignment Name
							//Due: 11/11/11T13:20
							//Submitted: Submitted or Not Submitted
							//Marks: 30 or Not Marked
					String anumber = Integer.toString(i+1);
					String aname = assignmentdata[0].split(",")[i];
					String adue = assignmentdata[1].split(",")[i];
					String amarks = assignmentdata[2].split(",")[i];
					String asub = assignmentdata[3].split(",")[i];
					String amaxmark = assignmentdata[4].split(",")[i];
					
					System.out.println(anumber + " - " + aname);
					System.out.println("\t\tDue:" + adue);
					System.out.println("\t\tSubmitted: " + asub);
					System.out.println("\t\tMarks: " + amarks + "/" + amaxmark);
					System.out.println("");
				}
				
				System.out.println("Enter the number of the assignment you wish");
				System.out.println("to view results in detail or make a submission.");
				System.out.println("Pressing 0 will go back to the previous screen");
				
				int inputchoice = Integer.parseInt(in.readLine());
				
				if (inputchoice == 0)
				{
					//Go Back
					studentUnitListUI(studentid);
				}
				else
				{
					//This will go on to the detail/submit assignment interface.
					studentCriteriaListUI(studentid, unitid, inputchoice-1);
				}
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
		}
		
		public void studentCriteriaListUI(String studentid, String unitid, int assignmentnumber)
		{
			try {
				String[] studentinfo = xmldata.getStudentInfo(studentid);
				String[] assignmentinfo = xmldata.getAssignmentInfo(studentid, unitid);
				String assignmentname = assignmentinfo[0].split(",")[assignmentnumber];
				String[] criteriainfo = xmldata.getCriteriaInfo(studentid, unitid, assignmentname);
				
				System.out.println("");
				//HIT1234 Development Assignment Details:
				System.out.println(unitid + " " + assignmentname + " Details:");
				//Submitted By Jacob Jones at 12:30PM
				System.out.println("Student: " + studentinfo[1] + " " + studentinfo[2]);
				System.out.println("Submitted: " + assignmentinfo[3].split(",")[assignmentnumber]);
				System.out.println("");
				
				for (int i = 0; i < criteriainfo[0].split(",").length; i++) {
					//For each criteria
					//Programming Skill
					System.out.println("Criteria: " + criteriainfo[0].split(",")[i]);
					//Description: A measure of programming skills
					System.out.println("Description: " + criteriainfo[1].split(",")[i]);
					
					//If marked:
					if ( (criteriainfo[3].split(",").length > (i)) && ( criteriainfo[3].split(",")[0].length() > 0))
					{
						//Marks: 10/20 Marks
						System.out.println("Marks: " + criteriainfo[3].split(",")[i] +"/"+ criteriainfo[2].split(",")[i]);
						//Feedback: Not leet enough
						System.out.println("Feedback: " + criteriainfo[4].split(",")[i]);
						//Marked by: John Smith
						System.out.println("Marked By: " + criteriainfo[5].split(",")[i]);
					}
					
					System.out.println("");
				}
				
				//Total Marks: 29/45
				System.out.println("Total Marks: " + assignmentinfo[2].split(",")[assignmentnumber] +"/" + assignmentinfo[4].split(",")[assignmentnumber]);
				
				System.out.println("Press 1 to submit an assignment");
				System.out.println("or 0 to go back");
				
				int inputchoice = Integer.parseInt(in.readLine());
				if (inputchoice == 1)
				{
					//Submit assignment
					xmldata.makeSubmission(studentid, unitid, assignmentname);
					//Go Back
					studentAssignmentListUI(studentid, unitid);
				}
				else
				{
					//Go Back
					studentAssignmentListUI(studentid, unitid);
				}
				
				
			}
			catch(Exception exp) {
				System.err.println(exp.toString());
			}
		}
		
	}

}















